﻿//////////////////////////////////////////////////////////////////////////////
//
// Copyright © 1998-2024 Glodon Company Limited.
//
// Licensed under the MIT License
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the “Software”),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
//////////////////////////////////////////////////////////////////////////////

#include "ExprNode.h"

#include "GbmpNew.h"
#include "TransferOwnership.h"

#include "EnableCompileWarning_The_LAST_IncludeInCpp.h"

using namespace gcmp;

ExprCustumNodeData::ExprCustumNodeData()
    : m_dataType(ExprDataType::Unknown)
    , m_pNode(nullptr)
{
    m_externStringValue.clear();
}

ExprCustumNodeData::~ExprCustumNodeData()
{
}

UnitMap ExprCustumNodeData::GetUnitType()
{
    return m_unitType;
}

void ExprCustumNodeData::SetUnitType(const UnitMap& unitType)
{
    m_unitType = unitType;
}

ExprDataType ExprCustumNodeData::GetType() const
{
    return m_dataType;
}

void ExprCustumNodeData::SetType(ExprDataType type)
{
    m_dataType = type;
}

void ExprCustumNodeData::SetAsInteger(long aValue)
{
    SetType(ExprDataType::Integer);
    m_value.IntegerValue = aValue;
}

long ExprCustumNodeData::GetAsInteger() const
{
    return m_value.IntegerValue;
}

void ExprCustumNodeData::SetAsBoolean(bool aValue)
{
    SetType(ExprDataType::Boolean);
    m_value.BooleanValue = aValue;
}

bool ExprCustumNodeData::GetAsBoolean() const
{
    return m_value.BooleanValue;
}

void ExprCustumNodeData::SetAsFloat(double aValue)
{
    SetType(ExprDataType::Float);
    m_value.FloatValue = aValue;
}

double ExprCustumNodeData::GetAsFloat() const
{
    return m_value.FloatValue;

}

void ExprCustumNodeData::SetAsString(const wchar_t* aValue)
{
    size_t length = wcslen(aValue);
    if (length < MAX_STRING_VALUE_LENGTH) // 先判断是否要开辟额外的空间
    {
        wcscpy(m_value.StringValue, aValue);
        m_externStringValue.clear();
    }
    else
    {
        m_externStringValue.resize(length + 1);
        wcscpy(&m_externStringValue[0], aValue);
    }
    m_dataType = ExprDataType::String;

}

const wchar_t* ExprCustumNodeData::GetAsString() const
{
    if (!m_externStringValue.empty())
        return &m_externStringValue[0];
    else
        return m_value.StringValue;
}


ExprCustumNode::ExprCustumNode()
    : m_opLeftChild(nullptr)
    , m_opRightChild(nullptr)
    , m_tag(nullptr)
    , m_token(ExprTokenType::EndInput)
    , m_nodeType(ExprType::UnaryOperate)
    , m_startPosition(0)
    , m_endPosition(0)
{
}

ExprCustumNode::ExprCustumNode(const ExprCustumNode& src)
{
}

ExprCustumNode& ExprCustumNode::operator=(const ExprCustumNode& src)
{
    return *this;
}

ExprCustumNode::~ExprCustumNode()
{
}

ExprType ExprCustumNode::GetNodeType() const
{
    return m_nodeType;
}

ExprNodeData* ExprCustumNode::GetData()
{
    return &m_data;
}

UnitMap ExprCustumNode::GetUnitType()
{
    return m_data.GetUnitType();
}

ExprDataType ExprCustumNode::GetDataType() const
{
    return m_data.GetType();
}

void ExprCustumNode::SetTag(void* aTag)
{
    m_tag = aTag;
}

void* ExprCustumNode::GetTag() const
{
    return m_tag;
}


ExprIDNode::ExprIDNode()
{
    m_nodeType = ExprType::ID;
    m_externStringValue.clear();
    wcscpy(m_stringValue, L"");
}

ExprIDNode::~ExprIDNode()
{
}

void ExprIDNode::SetNodeCode(const wchar_t* aValue)
{
    size_t length = wcslen(aValue);
    if (length < MAX_STRING_VALUE_LENGTH) // 先判断是否要开辟额外的空间
    {
        wcscpy(m_stringValue, aValue);
        m_externStringValue.clear();
    }
    else
    {
        m_externStringValue.resize(length + 1);
        wcscpy(&m_externStringValue[0], aValue);
    }
}

const wchar_t* ExprIDNode::GetNodeCode() const
{
    if (!m_externStringValue.empty())
        return &m_externStringValue[0];
    else
        return m_stringValue;
}


ExprNode* CustomFunctionParams::AppendParams(gcmp::OwnerPtr<ExprNode> aParam)
{
    if (!aParam)
        return nullptr;

    m_params.push_back(TransferOwnership(aParam));
    m_paramCount = (short)m_params.size();
    return m_params.back().get();
}

short CustomFunctionParams::Count() const
{
    return m_paramCount;
}

CustomFunctionParams::CustomFunctionParams()
{
    this->m_paramCount = 0;
}

CustomFunctionParams::~CustomFunctionParams()
{
}

ExprNodeData* CustomFunctionParams::GetParam(short aIndex)
{
    if (aIndex >= 0 && aIndex < m_paramCount)
        return m_params[aIndex]->GetData();
    else
        return nullptr;
}

const ExprNode* CustomFunctionParams::GetParamNode(short aIndex) const
{
    if (aIndex >= 0 && aIndex < m_paramCount)
        return m_params.at(aIndex).get();
    else
        return nullptr;
}

ExprNode* CustomFunctionParams::GetParamNodeFW(short aIndex)
{
    if (aIndex >= 0 && aIndex < m_paramCount)
        return m_params.at(aIndex).get();
    else
        return nullptr;
}


ExprNode* ExprFunctionNode::AppendParams(gcmp::OwnerPtr<ExprNode>& aParam)
{
    if (!aParam)
        return nullptr;

    return m_params.AppendParams(TransferOwnership(aParam));
}

const CustomFunctionParams* ExprFunctionNode::GetParams() const
{
    return &m_params;
}

CustomFunctionParams* ExprFunctionNode::GetParamsFW()
{
    return &m_params;
}

ExprFunctionNode::ExprFunctionNode()
{
    m_nodeType = ExprType::Function;
}

ExprFunctionNode::~ExprFunctionNode()
{
}
